%macro winsor(dsetin=, dsetout=, byvar=none, vars=, type=winsor, pctl=1 99);
%if &dsetout = %then %let dsetout = &dsetin;
%let varL=; %let varH=; %let xn=1; %do %until ( %scan(&vars,&xn)= );
%let token = %scan(&vars,&xn); %let varL = &varL &token.L; %let varH = &varH &token.H;
%let xn=%EVAL(&xn + 1); %end; %let xn=%eval(&xn-1);
data xtemp;
    set &dsetin;
    run;
%let dropvar = ;
%if &byvar = none %then %do;
    data xtemp;
       set xtemp;
       xbyvar = 1;
        run;
    %let byvar = xbyvar;
    %let dropvar = xbyvar;
%end;
proc sort data = xtemp;
    by &byvar;
    run;
proc univariate data = xtemp noprint;
    by &byvar;
    var &vars;
    output out = xtemp_pctl PCTLPTS = &pctl PCTLPRE = &vars PCTLNAME = L H;
    run;
data &dsetout;
    merge xtemp xtemp_pctl;
    by &byvar;
    array trimvars{&xn} &vars;
    array trimvarl{&xn} &varL;
    array trimvarh{&xn} &varH;
    do xi = 1 to dim(trimvars);
        %if &type = winsor %then %do;
            if trimvars{xi} ne . then do;
              if (trimvars{xi} < trimvarl{xi}) then trimvars{xi} = trimvarl{xi};
              if (trimvars{xi} > trimvarh{xi}) then trimvars{xi} = trimvarh{xi};
            end;
        %end;
        %else %do;
            if trimvars{xi} ne . then do;
              if (trimvars{xi} < trimvarl{xi}) then delete;
              if (trimvars{xi} > trimvarh{xi}) then delete;
            end;
        %end;
    end;
    drop &varL &varH &dropvar xi;
    run;
%mend winsor;
